package com.tansun.easycare.rule.ruleproj.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.tansun.easycare.core.service.impl.CrudServiceImpl;
import com.tansun.easycare.rule.common.BaseVO;
import com.tansun.easycare.rule.common.DataCache;
import com.tansun.easycare.rule.common.entity.RuleBaseEntity;
import com.tansun.easycare.rule.datamodel.entity.RuleDatamodel;
import com.tansun.easycare.rule.datamodel.entity.RuleDataparams;
import com.tansun.easycare.rule.datamodel.entity.RuleDataset;
import com.tansun.easycare.rule.datamodel.service.DataModelService;
import com.tansun.easycare.rule.datamodel.service.RuleDataparamsService;
import com.tansun.easycare.rule.rulemange.entity.RuleManage;
import com.tansun.easycare.rule.rulemange.service.RuleManageService;
import com.tansun.easycare.rule.ruleproj.dao.RuleProjectRankDao;
import com.tansun.easycare.rule.ruleproj.entity.RuleProject;
import com.tansun.easycare.rule.ruleproj.entity.RuleProjectRank;
import com.tansun.easycare.rule.ruleproj.service.RuleProjectRankService;
import com.tansun.easycare.rule.ruleproj.service.RuleProjectService;
import com.tansun.rule.common.RuleModelTypeEnum;
import com.tansun.rule.utils.StringUtils;

/**
 * 层级结构管理ServiceImpl
 * @author lph-zl
 * @version 2020-03-11
 */
@Service("ruleProjectRankService")
@Transactional(readOnly = true)
public class RuleProjectRankServiceImpl extends CrudServiceImpl<RuleProjectRankDao, RuleProjectRank> implements RuleProjectRankService{
	
	@Autowired
	RuleManageService ruleManageService;
	@Autowired
	DataModelService dataModelService;
	@Autowired
	RuleProjectService ruleProjectService;
	@Autowired
	RuleDataparamsService ruleDataparamsService;
	public RuleProjectRank get(String id) {
		return super.get(id);
	}
	
	public List<RuleProjectRank> findList(RuleProjectRank ruleProjectRank) {
		return super.findList(ruleProjectRank);
	}
	
	public List<RuleProjectRank> findAllList(String projectCode) {
		List<RuleProjectRank> rankList = null;
		String cacheKey = DataCache.getCacheKey(null, DataCache.RULE_PRO_RANK_MAP_OPTION);
		if( DataCache.canGetFromCache(cacheKey) ) {
			rankList = (List<RuleProjectRank>)DataCache.getValue(cacheKey);
		}else {
			RuleProjectRank rankCondition = new RuleProjectRank();
	        rankCondition.setProjectCode(projectCode);
	        rankList = super.findList(rankCondition);
	        DataCache.setValue(cacheKey, rankList);
		}
		return rankList;
	}
	
	public PageInfo<RuleProjectRank> findPage(Page<RuleProjectRank> page, RuleProjectRank ruleProjectRank) {
		return super.findPage(page, ruleProjectRank);
	}
	
	@Transactional(readOnly = false)
	public void save(RuleProjectRank ruleProjectRank) {
		//目前还需要将tid还原到ID上
		if(StringUtils.isEmpty(ruleProjectRank.getTid())) {
			//如果是修改，不执行此方法
			initSeq(ruleProjectRank);			
		}else {
			ruleProjectRank.setId(ruleProjectRank.getTid());
		}
		super.save(ruleProjectRank);
		DataCache.ruleProjectRankChange(ruleProjectRank.getProjectCode());
	}
	
	@Transactional(readOnly = false)
	public void delete(RuleProjectRank ruleProjectRank) {
		super.delete(ruleProjectRank);
	}
	
	/**
	 * 初始化排序好
	 * @param ruleProjectRank
	 */
	private void initSeq(RuleProjectRank ruleProjectRank) {
		if(ruleProjectRank.getSeq()!=null)
				return;
         if(!"file".equals(ruleProjectRank.getModuleType())) {
        	 //如果是新增组件，找到父节点下的所有节点，在最大的那个节点的基础上+1
    		 RuleProjectRank rankCondition = new RuleProjectRank();
             rankCondition.setProjectCode(ruleProjectRank.getProjectCode());
             rankCondition.setPId(ruleProjectRank.getPId());
             List<RuleProjectRank> ranklist = this.findList(rankCondition);
        	 if(ranklist==null || ranklist.size()==0) {
        		 ruleProjectRank.setSeq(31);
        	 }else {
        		 ruleProjectRank.setSeq(ranklist.get(ranklist.size()-1).getSeq() + 1);
        	 }
         }else {
        	 //如果是新增文件夹，找到父节点的序号+1
    		 RuleProjectRank rankCondition = new RuleProjectRank();
             rankCondition.setProjectCode(ruleProjectRank.getProjectCode());
             rankCondition.setNodeId(ruleProjectRank.getPId());
             List<RuleProjectRank> ranklist = this.findList(rankCondition);
             RuleProjectRank parentRank = ranklist.get(0);
             ruleProjectRank.setSeq(parentRank.getSeq() + 1);
         }
	}
	
	/**
	 * 查询规则记录数及数据集记录数信息（包含关联的变量及模型）
	 * @param tidArrList
	 * @return 
	 * @throws ClassNotFoundException 
	 */
	@Override
	public String findRefCount(String tidArr) {
		String msg="";
		String tidArrList[]=tidArr.split(",");
		int modeCount = 0;
		int manageCount = 0;
		String ruleMsg="";
		Map<String,Integer> mspMap = new HashMap<>();
		for(String tidObj:tidArrList) {
			String tidList[]=tidObj.split("@");
			String tid=tidList[0];
			String tidtype=tidList[1];
			if(tid!=null && tidtype!=null) {
				if("datamodel".equalsIgnoreCase(tidtype)) {
					RuleDataset condition = new RuleDataset();
					condition.setRankRelationId(tid);
					int listd = dataModelService.countList(condition);
					modeCount = modeCount+listd;
				}else if(!"file".equals(tidtype)){
					Integer count = 0;
					if(mspMap.containsKey(tidtype)) {
						count = mspMap.get(tidtype);
					}
					RuleManage condition = new RuleManage();
					condition.setRankRelationId(tid);
					int listm = ruleManageService.countList(condition);
					count +=listm;
					mspMap.put(tidtype, count);
					
				}					
			}						
		}
		Iterator iterator = mspMap.entrySet().iterator();
		 while(iterator.hasNext())
		   {
			   Map.Entry entry = (Map.Entry) iterator.next();
			   manageCount=  (Integer) entry.getValue();
			   String ttype = (String) entry.getKey();
			   String mType= translateName(ttype);
			   ruleMsg = ruleMsg+mType+":"+manageCount+"条\r\n";
			   
		   }

		if(modeCount!=0) {
			msg="该父节点下共有数据集"+modeCount+"个;\r\n";
		}if(manageCount!=0) {
			msg=msg+"该父节点下有已配置的"+ruleMsg;
		}
		return msg;
		
	}
	private String translateName(String tidtype) {
		String type =null;
		if("decisionTree".equals(tidtype)) {
			type="决策树";			
		}if("decisionTable".equals(tidtype)) {
			type="决策表";
		}if("singleTblIndex".equals(tidtype)) {
			type="决策表";
		}if("scoreModel".equals(tidtype)) {
			type="评分模型";
		}if("policyRuleGroup".equals(tidtype)) {
			type="规则集";
		}if("codeblock".equals(tidtype)) {
			type="脚本";
		}if("generalRule".equals(tidtype)) {
			type="规则";
		}if("func".equals(tidtype)) {
			type="规则函数";
		}if("datamining".equals(tidtype)) {
			type="数据挖掘";
		}if("ruleFlow".equals(tidtype)) {
			type="规则流";
		}if("funcparam".equals(tidtype)) {
			type="函数变量";
		}
		return type;
	}

	/**
	 * 删除层级信息（包含关联的变量及模型）
	 * @param tidArrList
	 */
	public void deleteRankInfo(String tidArr,String projectCode) throws Exception {
		if(StringUtils.isEmpty(tidArr))
			return;
		String msg = "";
		String tidArrList[]=tidArr.split(",");
		for(String tidObj:tidArrList) {
			String tidList[]=tidObj.split("@");
			String tid=tidList[0];
			String tidtype=tidList[1];
			if("datamodel".equalsIgnoreCase(tidtype)) {
				RuleDataset condition = new RuleDataset();
				condition.setRankRelationId(tid);
				List<RuleDataset> rds = dataModelService.findList(condition);
				if(rds!=null && rds.size()>0) {
					for (RuleDataset ruleDataset : rds) {
						msg += ruleDataset.getChzn() + " ; ";
					}
				}
				this.delete(new RuleProjectRank(tid));
			}else if("file".equals(tidList[1])){
				this.delete(new RuleProjectRank(tid));
			}else {
				RuleManage condition = new RuleManage();
				condition.setRankRelationId(tid);
				List<RuleManage> ruleInfo = ruleManageService.findList(condition);
				if(ruleInfo!=null && ruleInfo.size()>0) {
					for (RuleManage ruleManage : ruleInfo) {
						msg += ruleManage.getName() + " ; ";
					}
				}else {
					this.delete(new RuleProjectRank(tid));
				}
			}
		}
		if(!StringUtils.isEmpty(msg)) {
			throw new Exception("该模块存在数据："+msg+",如确定要删除，请先删除模型或将数据移动到其他模块");
		}
		DataCache.ruleProjectRankChange(projectCode);
	}
	/**
	 * 首次保存时调用此方法，初始化模块
	 * @param projectName
	 * @param projectCode
	 */
	@Transactional(readOnly = false)
	public void initBaseModule(String projectName,String projectCode,Boolean isUpdate,List<RuleProjectRank> curRanklist) {
//		if(curRanklist== null || curRanklist.size()!=22) {
		if(curRanklist== null || curRanklist.size()==0) {
			if(isUpdate) {//如果需要初始化数据， 需要获取项目名称
				RuleProject condition = new RuleProject();
				condition.setProjectcode(projectCode);
				List<RuleProject> ruleProjectList = ruleProjectService.findList(condition);
				if(ruleProjectList!=null && ruleProjectList.size()>0) {
					projectName = ruleProjectList.get(0).getProjectname();
				}
			}
			List<String> nodeIdList = new ArrayList<String>();
			for(RuleProjectRank rpr:curRanklist) {
				nodeIdList.add(rpr.getNodeId());
			}
			
			List<RuleProjectRank> rankList = new ArrayList<RuleProjectRank>();
			if(!nodeIdList.contains(projectCode)) {
				rankList.add(new RuleProjectRank(projectCode,"0",projectName,projectCode,"file",0));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			if(!nodeIdList.contains("dataModel")) {
				rankList.add(new RuleProjectRank("dataModel",projectCode,"数据模型",projectCode,"dataModel",31));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			if(!nodeIdList.contains("funcparam")) {
				rankList.add(new RuleProjectRank("funcparam",projectCode,"函数变量",projectCode,"funcparam",30));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			if(!nodeIdList.contains("generalRule")) {
				rankList.add(new RuleProjectRank("generalRule",projectCode,"规则",projectCode,"generalRule",32));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			if(!nodeIdList.contains("policyRuleGroup")) {
				rankList.add(new RuleProjectRank("policyRuleGroup",projectCode,"规则集",projectCode,"policyRuleGroup",39));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			if(!nodeIdList.contains("func")) {
				rankList.add(new RuleProjectRank("func",projectCode,"规则函数",projectCode,"func",33));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			if(!nodeIdList.contains("decisionTree")) {
				rankList.add(new RuleProjectRank("decisionTree",projectCode,"决策树",projectCode,"decisionTree",34));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
//			if(!nodeIdList.contains("decisionTable")) {
//				rankList.add(new RuleProjectRank("decisionTable",projectCode,"决策表",projectCode,"decisionTable",35));
////				curRanklist.add(rankList.get(rankList.size()-1));
//			}
			if(!nodeIdList.contains("singleTblIndex")) {
				rankList.add(new RuleProjectRank("singleTblIndex",projectCode,"决策表",projectCode,"singleTblIndex",36));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			if(!nodeIdList.contains("scoreModel")) {
				rankList.add(new RuleProjectRank("scoreModel",projectCode,"评分模型",projectCode,"scoreModel",37));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			if(!nodeIdList.contains("datamining")) {
				rankList.add(new RuleProjectRank("datamining",projectCode,"数据挖掘",projectCode,"datamining",38));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}		
			if(!nodeIdList.contains("executionBlock")){
			 	rankList.add(new RuleProjectRank("executionBlock",projectCode,"规则组",projectCode,"executionBlock",40));
//			 	curRanklist.add(rankList.get(rankList.size()-1));
			 }
			if(!nodeIdList.contains("codeblock")) {
				rankList.add(new RuleProjectRank("codeblock",projectCode,"脚本",projectCode,"codeblock",41));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			if(!nodeIdList.contains("ruleFlow")) {
				rankList.add(new RuleProjectRank("ruleFlow",projectCode,"决策流",projectCode,"ruleFlow",42));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			/**	
	  		if(!nodeIdList.contains("strategyFlow")){
	  			rankList.add(new RuleProjectRank("strategyFlow",projectCode," 策略流",projectCode,"ruleFlow",43));
	  			curRanklist.add(rankList.get(rankList.size()-1));
	 		}
			*/
			if(!nodeIdList.contains("ruleDeploy")) {
				rankList.add(new RuleProjectRank("ruleDeploy","1","规则部署",projectCode,"file",13));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			if(!nodeIdList.contains("ruleTest")) {
				rankList.add(new RuleProjectRank("ruleTest","ruleDeploy","单笔测试",projectCode,"ruleTest",14));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			if(!nodeIdList.contains("batchTest")) {
				rankList.add(new RuleProjectRank("batchTest","ruleDeploy","批量测试",projectCode,"batchTest",15));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			if(!nodeIdList.contains("deployOnline")) {
				rankList.add(new RuleProjectRank("deployOnline","ruleDeploy","联机部署",projectCode,"deployOnline",16));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
//			if(!nodeIdList.contains("calculationEngine")) {
//				rankList.add(new RuleProjectRank("calculationEngine","ruleDeploy","规则计算",projectCode,"calculationEngine",17));
////				curRanklist.add(rankList.get(rankList.size()-1));
//			}
			if(!nodeIdList.contains("ruleApproval")) {
				rankList.add(new RuleProjectRank("ruleApproval","1","规则审批",projectCode,"file",18));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			if(!nodeIdList.contains("ruleApprovalTodoList")) {
				rankList.add(new RuleProjectRank("ruleApprovalTodoList","ruleApproval","待办列表",projectCode,"ruleApprovalTodoList",19));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
			if(!nodeIdList.contains("ruleApprovalCompleteList")) {
				rankList.add(new RuleProjectRank("ruleApprovalCompleteList","ruleApproval","已办列表",projectCode,"ruleApprovalCompleteList",20));
//				curRanklist.add(rankList.get(rankList.size()-1));
			}
//			if(!nodeIdList.contains("ruleGlobalSearch")) {
//				rankList.add(new RuleProjectRank("ruleGlobalSearch",null,"规则搜索",projectCode,"ruleGlobalSearch",21));
////				curRanklist.add(rankList.get(rankList.size()-1));
//			}
			for (RuleProjectRank item : rankList) {
				this.save(item);
				if(isUpdate) {//初始化数据
					if("dataModel".equals(item.getNodeId())) {
						RuleDatamodel ruledataset = new RuleDatamodel();
						ruledataset.setProjectCode(item.getProjectCode());
						ruledataset.setRankRelationId(item.getId());
						dataModelService.updateRankId(ruledataset);
					}else if ("funcparam".equals(item.getNodeId())){
						RuleDataparams rd = new RuleDataparams();
						rd.setProjectcode(item.getProjectCode());
						rd.setRankRelationId(item.getId());
						ruleDataparamsService.updateRankId(rd);
					}else {
						if("ruleDeploy".equals(item.getNodeId())
								||"ruleTest".equals(item.getNodeId())
								||"batchTest".equals(item.getNodeId())
								||"deployOnline".equals(item.getNodeId())
//								||"calculationEngine".equals(item.getNodeId())
								||"ruleGlobalSearch".equals(item.getNodeId())) {
							continue;
						}
						if(RuleModelTypeEnum.getCode(item.getNodeId())==null)
							continue;
						RuleManage rulemanage = new RuleManage();
						rulemanage.setProjectCode(item.getProjectCode());
						rulemanage.setRankRelationId(item.getId());
						rulemanage.setModelType(RuleModelTypeEnum.getCode(item.getNodeId()));
						ruleManageService.updateRankId(rulemanage);
					}
				}
			}
//            RuleDataCollention<RuleProjectRank> ruleData = new RuleDataCollention<RuleProjectRank>();
//            ruleData.setList(rankList);
//            this.dao.insertBatch(ruleData);
		}
//		return curRanklist;
	}

	@Override
	public List<String> findIdsByRecursion(String id,String targetType) {
		List<String> resIds=new ArrayList<>();
		if( StringUtils.isNotEmpty(id) && !"undefined".equals(id)){ 
			RuleProjectRank sourceRank = this.get(id);
			List<RuleProjectRank> list = this.findAllList(sourceRank.getProjectCode());
			resIds = this.findParentRankIds(sourceRank.getPId(), targetType, list);
			if(sourceRank.getModuleType().equals(targetType)) {
				resIds.add(id);
			}
		}
		return resIds;
	}
	
	/**
	 * 递归查找 rankids
	 * @param pid
	 * @param targetType
	 * @param list
	 * @return
	 */
	public List<String> findParentRankIds(String pid, String targetType, List<RuleProjectRank> list) {
		List<String> resIds = new ArrayList<String>();
		for(RuleProjectRank rank:list) {
			if( ( StringUtils.isNotEmpty(rank.getPId()) && rank.getPId().equals(pid)) && ( StringUtils.isEmpty(targetType) || targetType.equals(rank.getModuleType()) ) ) {//查找同目录下的组件
				resIds.add(rank.getTid());
			}
			if( rank.getNodeId().equals(pid)) {
				resIds.addAll(findParentRankIds(rank.getPId(), targetType, list));
			}
		}
		return resIds;
	}

	@Override
	public void setRefRandIds(RuleBaseEntity<?> obj,boolean isRecursion) {
		// TODO Auto-generated method stub
		String rankId = obj.getRankRelationId();
		if(StringUtils.isNotEmpty(rankId)) {
			List<String> ids = null;
			if(isRecursion) {
				ids = findIdsByRecursion(rankId,null);
			}else {
				ids = new ArrayList<String>();
				ids.add(rankId);
			}
			obj.setRankRelationIds(ids);
		}
	}

	@Override
	public void setRefRandIds(BaseVO<?> obj,boolean isRecursion) {
		// TODO Auto-generated method stub
		String rankId = obj.getRankRelationId();
		if(StringUtils.isNotEmpty(rankId)) {
			List<String> ids = null;
			if(isRecursion) {
				ids = findIdsByRecursion(rankId,null);
			}else {
				ids = new ArrayList<String>();
				ids.add(rankId);
			}
			obj.setRankRelationIds(ids);
		}
	}

	@Override
	public void closeTree(List<RuleProjectRank> rankList) {
		if(rankList!=null&&rankList.size()>0) {
			String projectCode = rankList.get(0).getProjectCode();
	        for (RuleProjectRank dataset : rankList) {
	        	if("file".equals(dataset.getModuleType())&&projectCode.equals(dataset.getPId())) {
	        		dataset.setOpen(false);
	        	}
	        }
		}
	}

	@Override
	public RuleProjectRank findIdByIdType(String brId, String targetType) {
		Map<String,String> map = new HashMap<String,String>();
		map.put("id", brId);
		map.put("targetType", targetType);
		return this.dao.findIdByIdType(map);
	}

	@Override
	public void sortTree(List<RuleProjectRank> rankList) {
		Collections.sort(rankList, new Comparator<RuleProjectRank>() {
				@Override
				public int compare(RuleProjectRank u1, RuleProjectRank u2) {
						int diff = u1.getSeq() - u2.getSeq();
						if (diff > 0) {
							return 1;
						}else if (diff < 0) {
							return -1;
						}else {
							return 0;
						}
				}
			}); 
	}
}